package com.coolgor.coldot.service.wechat.gzh.impl;

import com.coolgor.coldot.common.wechat.HttpUtil;
import com.coolgor.coldot.dao.wechat.gzh.GZHAccessTokenDao;
import com.coolgor.coldot.dto.wechat.gzh.GZHAccessTokenExecution;
import com.coolgor.coldot.entity.wechat.gzh.GZHAccessToken;
import com.coolgor.coldot.enums.wechat.gzh.GZHAccessTokenOperationStateEnum;
import com.coolgor.coldot.service.wechat.gzh.GZHAccessTokenService;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.Date;
import java.util.Map;

@Service
public class GZHAccessTokenServiceImpl implements GZHAccessTokenService {

    private static Logger log = LoggerFactory.getLogger(GZHAccessTokenServiceImpl.class);

    @Autowired
    GZHAccessTokenDao gzhAccessTokenDao;

    @Override
    public GZHAccessTokenExecution getGZHAccessToken(Long recordID) {
        GZHAccessToken gzhAccessToken = gzhAccessTokenDao.queryByRecordID(recordID);
        if ( null == gzhAccessToken ) {
            return new GZHAccessTokenExecution(GZHAccessTokenOperationStateEnum.NULL);
        }
        //获取当前时间，并且延长100秒
        Date nowdate = new Date(System.currentTimeMillis()+100*1000);
        //当出现以下情况时
        //1、数据库中的AccessToken记录为空
        //2、数据库中InvalidTime时效时间为空
        //3、这个延长了100秒的时间超出了AccessToken的失效时间
        //则进行重新联网获取AccessToken
        if ( null == gzhAccessToken.getAccessToken()
                || null == gzhAccessToken.getInvalidTime()
                || nowdate.after(gzhAccessToken.getInvalidTime())) {
            // https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
            String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="+gzhAccessToken.getAppID()+"&secret="+gzhAccessToken.getSecret();
            String tokenStr = HttpUtil.httpsRequest(url, "GET", null);
            ObjectMapper objectMapper = new ObjectMapper();
            Map<String, Object> tokenMap = null;
            try {
                // 将json字符串转换成相应对象
                tokenMap = objectMapper.readValue(tokenStr, Map.class);
            } catch (JsonParseException e) {
                log.error("从腾讯服务器中获取accessToken失败: " + e.getMessage());
                e.printStackTrace();
            } catch (JsonMappingException e) {
                log.error("从腾讯服务器中获取accessToken失败: " + e.getMessage());
                e.printStackTrace();
            } catch (IOException e) {
                log.error("从腾讯服务器中获取accessToken失败: " + e.getMessage());
                e.printStackTrace();
            }
            if ( null == tokenMap
                    || (null!=tokenMap.get("errcode") && !"0".equals(tokenMap.get("errcode"))) ) {
                log.error("获取公众号accessToken失败。");
                System.out.println(">>>>>>tokenMap>>>>> ");
                System.out.println(tokenMap.toString());
                return new GZHAccessTokenExecution(GZHAccessTokenOperationStateEnum.INNER_ERROR);
            } else if (null == tokenMap.get("errcode") || (int)tokenMap.get("errcode")==0) {
                gzhAccessToken.setAccessToken((String) tokenMap.get("access_token"));
                gzhAccessToken.setExpireTime((int) tokenMap.get("expires_in"));
                gzhAccessToken.setCreateTime(new Date(System.currentTimeMillis()-100*1000));
                gzhAccessToken.setInvalidTime(new Date(System.currentTimeMillis()-100*1000+gzhAccessToken.getExpireTime()*1000));
                int effectNum = gzhAccessTokenDao.update(gzhAccessToken);
                if (effectNum == 1) {
                    return new GZHAccessTokenExecution(GZHAccessTokenOperationStateEnum.SUCCESS,gzhAccessToken);
                } else {
                    log.error("在数据库中更新公众号accessToken失败。");
                    return new GZHAccessTokenExecution(GZHAccessTokenOperationStateEnum.INNER_ERROR);
                }
            }
        }
        return new GZHAccessTokenExecution(GZHAccessTokenOperationStateEnum.SUCCESS,gzhAccessToken);
    }

    @Override
    public GZHAccessTokenExecution getGZHAccessToken(String appID) {
        if (null==appID || "".equals(appID)) return null;
        GZHAccessToken gzhAccessToken = gzhAccessTokenDao.queryByAppID(appID);
        if ( null == gzhAccessToken ) {
            return new GZHAccessTokenExecution(GZHAccessTokenOperationStateEnum.NULL);
        }
        //获取当前时间，并且延长100秒
        Date nowdate = new Date(System.currentTimeMillis()+100*1000);
        //当出现以下情况时
        //1、数据库中的AccessToken记录为空
        //2、数据库中InvalidTime时效时间为空
        //3、这个延长了100秒的时间超出了AccessToken的失效时间
        //则进行重新联网获取AccessToken
        if ( null == gzhAccessToken.getAccessToken()
                || null == gzhAccessToken.getInvalidTime()
                || nowdate.after(gzhAccessToken.getInvalidTime())) {
            // https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
            String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="+gzhAccessToken.getAppID()+"&secret="+gzhAccessToken.getSecret();
            String tokenStr = HttpUtil.httpsRequest(url, "GET", null);
            ObjectMapper objectMapper = new ObjectMapper();
            Map<String, Object> tokenMap = null;
            try {
                // 将json字符串转换成相应对象
                tokenMap = objectMapper.readValue(tokenStr, Map.class);
            } catch (JsonParseException e) {
                log.error("从腾讯服务器中获取accessToken失败: " + e.getMessage());
                e.printStackTrace();
            } catch (JsonMappingException e) {
                log.error("从腾讯服务器中获取accessToken失败: " + e.getMessage());
                e.printStackTrace();
            } catch (IOException e) {
                log.error("从腾讯服务器中获取accessToken失败: " + e.getMessage());
                e.printStackTrace();
            }
            if ( null == tokenMap
                    || (null!=tokenMap.get("errcode") && !"0".equals(tokenMap.get("errcode"))) ) {
                log.error("获取公众号accessToken失败。");
                System.out.println(">>>>>>tokenMap>>>>> ");
                System.out.println(tokenMap.toString());
                return new GZHAccessTokenExecution(GZHAccessTokenOperationStateEnum.INNER_ERROR);
            } else if (null == tokenMap.get("errcode") || (int)tokenMap.get("errcode")==0) {
                gzhAccessToken.setAccessToken((String) tokenMap.get("access_token"));
                gzhAccessToken.setExpireTime((int) tokenMap.get("expires_in"));
                gzhAccessToken.setCreateTime(new Date(System.currentTimeMillis()-100*1000));
                gzhAccessToken.setInvalidTime(new Date(System.currentTimeMillis()-100*1000+gzhAccessToken.getExpireTime()*1000));
                int effectNum = gzhAccessTokenDao.update(gzhAccessToken);
                if (effectNum == 1) {
                    return new GZHAccessTokenExecution(GZHAccessTokenOperationStateEnum.SUCCESS,gzhAccessToken);
                } else {
                    log.error("在数据库中更新公众号accessToken失败。");
                    return new GZHAccessTokenExecution(GZHAccessTokenOperationStateEnum.INNER_ERROR);
                }
            }
        }
        return new GZHAccessTokenExecution(GZHAccessTokenOperationStateEnum.SUCCESS,gzhAccessToken);
    }
}
